import React, {
    useImperativeHandle,
    useRef,
    useEffect,
    useCallback,
    useState,
    forwardRef
} from 'react'
import { getTransitionEndName } from 'utils/index'
function Barrage(props, ref) {
    const { barrages } = props
    const barrageRef = useRef()
    const [fontSize] = useState(() => '0.8rem')
    const [opacity] = useState(1)
    const [randomTop, setRandomTop] = useState(0)
    const [viewWidth, setViewWidth] = useState(0)
    const [viewHeight, setViewHeight] = useState(0)
    const [fixedTop, setFixedTop] = useState(0)
    const [contentHeight, setContentHeight] = useState(0)
    useImperativeHandle(ref, () => ({
        // changeVal 就是暴露给父组件的方法
        sendone: (barrage) => {
            const barrageDOM = barrageRef.current
            const barrageElem = createBarrageElem(barrage)
            barrageDOM.appendChild(barrageElem)
        },
        clearall: () => {
            setRandomTop(0)
            setFixedTop(0)
            const barrageDOM = barrageRef.current
            const children = barrageDOM.children
            for (const child of Array.from(children)) {
                barrageDOM.removeChild(child)
            }
        }
    }))
    useEffect(() => {
        refresh()
        const div = document.createElement('div')
        div.innerHTML = 'div'
        div.style.fontSize = fontSize
        const body = document.getElementsByTagName('body')[0]
        body.appendChild(div)
        // 弹幕内容高度
        setContentHeight(div.offsetHeight)
        body.removeChild(div)
        if (barrages) {
            for (const barrage of barrages) {
                send(barrage)
            }
        }
        return () => {
            clear()
        }
    })
    const clear = useCallback(() => {
        setRandomTop(0)
        setFixedTop(0)
        const barrageDOM = barrageRef.current
        const children = barrageDOM.children
        for (const child of Array.from(children)) {
            barrageDOM.removeChild(child)
        }
    })
    const send = useCallback((barrage) => {
        const barrageDOM = barrageRef.current
        const barrageElem = createBarrageElem(barrage)
        barrageDOM.appendChild(barrageElem)
    })
    const createBarrageElem = useCallback((barrage) => {
        const div = document.createElement('div')
        div.innerHTML = barrage.content

        const style = {
            position: 'absolute',
            fontFamily: '黑体',
            fontSize: '0.8rem',
            fontWeight: 'bold',
            whiteSpace: 'pre',
            textShadow: 'rgb(0, 0, 0) 1px 1px 2px',
            color: barrage.color,
            opacity
        }
        // 随机滚动
        if (barrage.type !== 2) {
            style.top = `${randomTop}px`
            style.left = `${viewWidth}px`
            style.webkitTransition = '-webkit-transform 5s linear 0s'
            style.transition = 'transform 5s linear 0s'

            const transitionName = getTransitionEndName(div)
            const handleTransitionEnd = () => {
                // 弹幕运动完成后移除监听，清除弹幕
                div.removeEventListener(transitionName, handleTransitionEnd)
                barrageRef.current.removeChild(div)

                // 距顶端位置减少一个弹幕内容高度
                setRandomTop((randomTop) => randomTop - contentHeight)
                // 最小值边界判断
                if (randomTop < 0) {
                    setRandomTop(0)
                }
            }
            div.addEventListener(transitionName, handleTransitionEnd)
            // 距离顶端位置增加一个弹幕内容高度，防止滚动弹幕重叠
            setRandomTop((randomTop) => randomTop + contentHeight)
            // 最大值边界判断
            if (randomTop > viewHeight - contentHeight) {
                setRandomTop(0)
            }
        } else {
            div.style.top = fixedTop + 'px'
            // 距离顶端位置增加一个弹幕内容高度，防止固定弹幕重叠
            setFixedTop((fixedTop) => fixedTop + contentHeight)
            // 最大值边界判断
            if (fixedTop > viewHeight - contentHeight) {
                setFixedTop(0)
            }
        }

        for (const k in style) {
            if (style[k] !== void 0) {
                div.style[k] = style[k]
            }
        }

        return div
    })
    const refresh = useCallback(() => {
        const barrageDOM = barrageRef.current
        setViewWidth(barrageDOM.offsetWidth)
        setViewHeight(barrageDOM.offsetHeight)
    })
    return <div ref={barrageRef} className="bar-col"></div>
}

export default forwardRef(Barrage)
